package cc.rengu.igas.mcps.core.service.base;

import cc.rengu.igas.mcps.common.constant.McpsParamConstant;
import cc.rengu.igas.mcps.common.constant.McpsTreeNodeConstant;
import cc.rengu.igas.mcps.common.enums.RespCodeEnum;
import cc.rengu.igas.mcps.core.realize.PosPublicCheckService;
import cc.rengu.igas.mcps.core.realize.impl.PosPublicCheckServiceImpl;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.realize.impl.RiskMonitorServiceImpl;
import cc.rengu.oltp.service.base.BizBaseService;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.RiskMonitorInfo;
import cc.rengu.oltp.service.realize.RiskMonitorService;
import cc.rengu.oltp.utility.annotation.BIZ_AFTER;
import cc.rengu.oltp.utility.annotation.BIZ_BEFORE;
import cc.rengu.oltp.utility.annotation.BIZ_PROCESS;
import cc.rengu.oltp.utility.util.AmountUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;

/**
 * 条码统一接入退款服务基类
 */
/*主流程，sn序列号校验，mac验签校验，签到校验，地理位置校验,校验预授权
 * */
public abstract class QrRefundService extends BizBaseService {
    @Override
    protected Object beforeBizProcess() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String channelId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_CHANNEL_ID);
        String instId = xmlTreeUtil.getXmlTreeStringValue(McpsTreeNodeConstant.INST_ID);
        String mchntNo = xmlTreeUtil.getXmlTreeStringValue(McpsTreeNodeConstant.MCHNT_NO);
        String refundAmt = xmlTreeUtil.getXmlTreeStringValue(McpsTreeNodeConstant.TRANS_AMT);

        /* 金额不允许出现负数金额及0金额 */
        if (!StringUtil.isEmptyOrNull(refundAmt) && AmountUtil.compare(refundAmt, "0") <= 0) {
            rglog.error("金额不合法,{}", refundAmt);
            throw new BizException(RespCodeEnum.REQUEST_ERROR.getRespCode(), RespCodeEnum.REQUEST_ERROR.getRespDesc());
        }
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.ORDER_AMT, refundAmt);

        /* Step1：查找BIZ_BEFORE的注解*/
        invokeBizAnnoMethod(BIZ_BEFORE.class);

        /* Step2：金融类交易公共校验 */
        PosPublicCheckService posPublicCheckService = new PosPublicCheckServiceImpl();
        if (McpsParamConstant.REQ_NPOS_ID.equals(channelId)) {
            /* Step2.1：mac验签，地理位置校验，sn校验，签到校验 */
            posPublicCheckService.posPublicCheckService();
        } else if (McpsParamConstant.REQ_ILLT_ID.equals(channelId)) {
            /* Step2.2：大型智能终端公共校验 */
            posPublicCheckService.illtPublicCheckService();
        } else if (!McpsParamConstant.REQ_H5_ID.equals(channelId)) {
            rglog.error("请求渠道<{}>不支持!", channelId);
            throw new BizException(RespCodeEnum.REQUEST_ERROR.getRespCode(), RespCodeEnum.REQUEST_ERROR.getRespDesc());
        }

        /* Step3：商户和终端的业务权限校验 */
        posPublicCheckService.posPublicAuthCtrlCheckService(txnInfo);

        /* Step4：退款检查 */
        posPublicCheckService.posPublicRefundCheckService();

        /* Step5：累计退款限额检查 */
        MchntService mchntService = new MchntServiceImpl();
        boolean checkResult = mchntService.checkMchntRefundLimit(instId, mchntNo, refundAmt);
        if (!checkResult) {
            rglog.error("商户<{}>退款限额超限!", mchntNo);
            throw new BizException(RespCodeEnum.REFUND_AMT_OVER.getRespCode(), RespCodeEnum.REFUND_AMT_OVER.getRespDesc());
        }

        /* Step6：交易处理前客户化 */
        return bizBeforeCust();
    }

    @Override
    protected BizResponse callBizService(Object request) throws Exception {
        /* Step1：查找BIZ_PROCESS的注解 */
        invokeBizAnnoMethod(BIZ_PROCESS.class);

        /* Step2：业务逻辑处理*/
        return bizProcessCust(request);
    }

    @Override
    protected void afterBizProcess(BizResponse response) throws Exception {
        /* Step2：查找BIZ_AFTER的注解 */
        invokeBizAnnoMethod(BIZ_AFTER.class);
        /* Step3：业务调用后客户化处理 */
        bizAfterCust(response);
    }

    @Override
    protected RiskMonitorInfo getRiskMonitorInfo() {
        RiskMonitorInfo riskMonitorInfo = new RiskMonitorInfo();
        RiskMonitorService riskMonitorService = new RiskMonitorServiceImpl();
        riskMonitorInfo.setTransMonitor(riskMonitorService);
        return riskMonitorInfo;
    }

    /**
     * 业务处理前客户化处理
     *
     * @return 业务处理实体类
     */
    protected abstract Object bizBeforeCust() throws Exception;

    /**
     * 业务逻辑处理客户化处理
     *
     * @param request 业务处理前的返回实体类
     * @return 业务处理结果
     */
    protected abstract BizResponse bizProcessCust(Object request) throws Exception;

    /**
     * 业务处理后逻辑处理
     *
     * @param response 业务调用响应信息
     */
    protected abstract void bizAfterCust(Object response) throws Exception;
}
